package ch4.DataBasedSeparation;

import jdk.nashorn.internal.runtime.ECMAException;
import util.Debug;
import util.Tools;

import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 大文件下载器
 */

public class BigFileDownloader {
    protected final URL requestURL;
    protected final long fileSize;

    /**
     * 负责已下载数据的存储
     * 并且storage也是负责存储所有线程下载的整个数据
     * 每个线程都下载一部分数据，然后把这些数据都写到storage中
     */
    protected final Storage storage;
    protected final AtomicBoolean taskCanceled = new AtomicBoolean(false);

    public BigFileDownloader(String strURL) throws Exception {
        requestURL = new URL(strURL);

        // 获取等待下载资源的大小
        fileSize = retieveFileSize(requestURL);
        Debug.info("file total size: %s", fileSize);
        String fileName = strURL.substring(strURL.lastIndexOf('/') + 1);
        // 创建负责存储已下载数据的对象
        storage = new Storage(fileSize, fileName);
    }

    /**
     * 下载指定的文件
     */
    public void download(int taskCount, long reportInterval) throws Exception {
        long chunkSizePerThread = fileSize / taskCount;
        // 下载数据段的起始字节
        long lowerBound = 0;
        // 下载数据段的结束字节
        long upperBound = 0;
        DownloadTask dt;
        for (int i = taskCount - 1; i >= 0; i--) {
            lowerBound = i * chunkSizePerThread;
            if (i == taskCount - 1) {
                upperBound = fileSize;
            } else {
                upperBound = lowerBound + chunkSizePerThread - 1;
            }
            // 创建下载任务
            dt = new DownloadTask(lowerBound, upperBound, requestURL, storage, taskCanceled);
            dispatchWork(dt, i);
        }
        // 定时报告下载进度
        reportProgress(reportInterval);
        // 清理程序占用的资源
        doCleanup();
    }

    protected void doCleanup() {
        Tools.silentClose(storage);
    }

    protected void cancelDownload() {
        if (taskCanceled.compareAndSet(false, true)) {
            doCleanup();
        }
    }

    protected void dispatchWork(final DownloadTask dt, int workIndex) {
        // 创建下载线程
        Thread workerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    dt.run();
                } catch (Exception e) {
                    e.printStackTrace();
                    // 取消整个文件的下载
                    cancelDownload();
                }
            }
        });
        workerThread.setName("downloader-" + workIndex);
        workerThread.start();
    }

    // 根据指定的URL获取相应的文件大小
    private static long retieveFileSize(URL requestURL) throws Exception {
        return 0;
    }

    private void reportProgress(long reportInterval) throws InterruptedException {

    }
}
